package net.helix.core.loader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Scanner;

import net.helix.core.geometry.Geometry_Image;
import net.helix.core.geometry.Geometry_Material;
import net.helix.engine.Engine;
import net.helix.engine.library.items.LibraryItem_Image;
import net.helix.engine.library.items.LibraryItem_Material;
import net.helix.ui.panels.library.LibraryTreeTableModel;

/**
 * .mtl loader which loads the contents of the .mtl file as Materials
 * and loads the necessary textures into the library automatically.
 * Materials defined in this .mtl file should be added to the library
 * as well as the Textures that are specified.
 * 
 * @author Runouw
 *
 */
public class MTLLoader {
	private Engine engine;
	private LibraryTreeTableModel treeModel;
	
	private HashMap<String, Geometry_Material> materials;
	private Geometry_Material currentMaterial;
	
	private File file;
	public MTLLoader(Engine engine, LibraryTreeTableModel treeModel, String addr){
		System.out.println("Load mtl "+addr);
		
		this.engine = engine;
		this.treeModel = treeModel;
		
		file = new File(addr);
		
		materials = new HashMap<String, Geometry_Material>();
		currentMaterial = null;
		
		FileInputStream fin = null;
		
		try {
			fin = new FileInputStream(file);
			
			InputStreamReader finr = new InputStreamReader(fin, "UTF-8");
			
			Scanner scanner = new Scanner(finr);
			while(scanner.hasNextLine()){
				readLine(scanner.nextLine());
			}
			
			scanner.close();
			//finr.close();
			//fin.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	private String removeComments(String line){
		if(line.contains("#")){
			return line.substring(0, line.indexOf('#'));
		}else{
			return line;
		}
	}
	private void readLine(String line){
		line = removeComments(line);
		
		// skips line if it is determined a comment
		// checks the beginning of each line (v, vt, vn, f, ect) and calls a function to handle it
		for(int i=0;i<line.length();i++){
			
			
			if(line.charAt(i) == ' '){
				continue;
			}else if(line.charAt(i) == '\t'){
				continue;
			}else if(line.charAt(i) == '#'){
				// comment, time to get out of here...
				return;
			}else if(i + 6 < line.length() && line.charAt(i) == 'n' && line.charAt(i+1) == 'e' && line.charAt(i+2) == 'w' && line.charAt(i+3) == 'm' && line.charAt(i+4) == 't' && line.charAt(i+5) == 'l' && line.charAt(i+6) == ' '){
				newMaterial(line.substring(i+7));
				
				return;
			}else if(i + 6 < line.length() && line.charAt(i) == 'm' && line.charAt(i+1) == 'a' && line.charAt(i+2) == 'p' && line.charAt(i+3) == '_' && line.charAt(i+4) == 'K' && line.charAt(i+5) == 'a' && line.charAt(i+6) == ' '){
				map_Ka(line.substring(i+7));
				
				return;
			}else if(i + 6 < line.length() && line.charAt(i) == 'm' && line.charAt(i+1) == 'a' && line.charAt(i+2) == 'p' && line.charAt(i+3) == '_' && line.charAt(i+4) == 'K' && line.charAt(i+5) == 'd' && line.charAt(i+6) == ' '){
				map_Kd(line.substring(i+7));
				
				return;
			}else if(i + 6 < line.length() && line.charAt(i) == 'm' && line.charAt(i+1) == 'a' && line.charAt(i+2) == 'p' && line.charAt(i+3) == '_' && line.charAt(i+4) == 'K' && line.charAt(i+5) == 's' && line.charAt(i+6) == ' '){
				map_Ks(line.substring(i+7));
				
				return;
			}else if(i + 5 < line.length() && line.charAt(i) == 'm' && line.charAt(i+1) == 'a' && line.charAt(i+2) == 'p' && line.charAt(i+3) == '_' && line.charAt(i+4) == 'd' && line.charAt(i+5) == ' '){
				map_d(line.substring(i+6));
				
				return;
			}else if(i + 2 < line.length() && line.charAt(i) == 'K' && line.charAt(i+1) == 'a' && line.charAt(i+2) == ' '){
				Ka(line.substring(i+2));
				
				return;
			}else if(i + 2 < line.length() && line.charAt(i) == 'K' && line.charAt(i+1) == 'd' && line.charAt(i+2) == ' '){
				Kd(line.substring(i+2));
				
				return;
			}else if(i + 2 < line.length() && line.charAt(i) == 'K' && line.charAt(i+1) == 's' && line.charAt(i+2) == ' '){
				Ks(line.substring(i+2));
				
				return;
			}else if(i + 2 < line.length() && line.charAt(i) == 'K' && line.charAt(i+1) == 's' && line.charAt(i+2) == ' '){
				Ke(line.substring(i+2));
				
				return;
			}else if(i + 1 < line.length() && line.charAt(i) == 'd' && line.charAt(i+1) == ' '){
				d(line.substring(i+1));
				
				return;
			}else if(i + 5 < line.length() && line.charAt(i) == 'i' && line.charAt(i+1) == 'l' && line.charAt(i+2) == 'l' && line.charAt(i+3) == 'u' && line.charAt(i+4) == 'm' && line.charAt(i+5) == ' '){
				illum(line.substring(i+6));
				
				return;
			}
		}
		
	}
	private int materialCount = 0;
	private void newMaterial(String line){
		line = removeComments(line);
		
		Geometry_Material material = new Geometry_Material();
		
		materials.put(line, material);
		
		currentMaterial = material;
		
		if(line.contains("-fx")){
			String p = file.getParent();
			p = p.substring(0, p.indexOf('.'));
			if((""+p.charAt(p.length()-1)).equals(File.separator)){
				p = p.substring(0, p.length()-1);
			}
			
			System.out.println("Parent is "+p);
			System.out.println("Trying "+ (p + File.separator + line.split("-fx")[0] + ".png"));
			
			try{
				Geometry_Image image = engine.loadImageAndAddToLibrary(treeModel, p + File.separator + line.split("-fx")[0] + ".png");
				material.setTextureKd(image);
			}catch(Exception e){
				
			}
			
		}
		
		if(treeModel != null){
			// add to library
			LibraryItem_Material newMTL = new LibraryItem_Material(treeModel.getLibrary(), "material "+(++materialCount), material); 
			
			Engine.addLoadingText("Adding "+newMTL.name + ".");
			treeModel.addNewItem(newMTL);
		}
		
		
	}
	private void map_Ka(String line){
		line = removeComments(line);
		
		String addr = file.getParent() + File.separator + line;
		Geometry_Image image = engine.loadImageAndAddToLibrary(treeModel, addr);
		currentMaterial.setTextureKa(image);
	}
	private void map_Kd(String line){
		line = removeComments(line);
		
		String addr = file.getParent() + File.separator + line;
		Geometry_Image image = engine.loadImageAndAddToLibrary(treeModel, addr);
		currentMaterial.setTextureKd(image);
	}
	private void map_Ks(String line){
		line = removeComments(line);
		
		String addr = file.getParent() + File.separator + line;
		Geometry_Image image = engine.loadImageAndAddToLibrary(treeModel, addr);
		currentMaterial.setTextureKs(image);
	}
	private void map_d(String line){
		line = removeComments(line);
		
		String addr = file.getParent() + File.separator + line;
		Geometry_Image image = engine.loadImageAndAddToLibrary(treeModel, addr);
		currentMaterial.setTextureD(image);
	}
	
	private void Ka(String line){
		line = removeComments(line);
		
		String[] arr = line.split(" ");
		
		float x = 0;
		float y = 0;
		float z = 0;
		
		int h = 0;
		for(int i=0;i<arr.length;i++){
			if(!arr[i].equals("")){
				h++;
				switch(h){
				case 1:
					x = Float.parseFloat(arr[i]);
					break;
				case 2:
					y = Float.parseFloat(arr[i]);
					break;
				case 3:
					z = Float.parseFloat(arr[i]);
					break;
				default:
					break;
				}
			}
		}
		
		if(currentMaterial != null){
			currentMaterial.setAmbient(x, y, z, 1);
		}
		
		
	}
	private void Kd(String line){
		line = removeComments(line);
		
		String[] arr = line.split(" ");
		
		float x = 0;
		float y = 0;
		float z = 0;
		
		int h = 0;
		for(int i=0;i<arr.length;i++){
			if(!arr[i].equals("")){
				h++;
				switch(h){
				case 1:
					x = Float.parseFloat(arr[i]);
					break;
				case 2:
					y = Float.parseFloat(arr[i]);
					break;
				case 3:
					z = Float.parseFloat(arr[i]);
					break;
				default:
					break;
				}
			}
		}
		
		if(currentMaterial != null){
			currentMaterial.setDiffuse(x, y, z, 1);
		}
		
		
	}
	private void Ks(String line){
		line = removeComments(line);
		
		String[] arr = line.split(" ");
		
		float x = 0;
		float y = 0;
		float z = 0;
		
		int h = 0;
		for(int i=0;i<arr.length;i++){
			if(!arr[i].equals("")){
				h++;
				switch(h){
				case 1:
					x = Float.parseFloat(arr[i]);
					break;
				case 2:
					y = Float.parseFloat(arr[i]);
					break;
				case 3:
					z = Float.parseFloat(arr[i]);
					break;
				default:
					break;
				}
			}
		}
		
		if(currentMaterial != null){
			currentMaterial.setSpecular(x, y, z, 1);
		}
		
		
	}
	private void Ke(String line){
		line = removeComments(line);
		
		String[] arr = line.split(" ");
		
		float x = 0;
		float y = 0;
		float z = 0;
		
		int h = 0;
		for(int i=0;i<arr.length;i++){
			if(!arr[i].equals("")){
				h++;
				switch(h){
				case 1:
					x = Float.parseFloat(arr[i]);
					break;
				case 2:
					y = Float.parseFloat(arr[i]);
					break;
				case 3:
					z = Float.parseFloat(arr[i]);
					break;
				default:
					break;
				}
			}
		}
		
		if(currentMaterial != null){
			currentMaterial.setEmission(x, y, z, 1);
		}
		
		
	}
	
	private void illum(String line){
		line = removeComments(line);
		
		String[] arr = line.split(" ");
		
		int value = 0;
		
		int h = 0;
		for(int i=0;i<arr.length;i++){
			if(!arr[i].equals("")){
				h++;
				switch(h){
				case 1:
					value = Integer.parseInt(arr[i]);
					break;
				default:
					break;
				}
			}
		}
		
		if(currentMaterial != null){
			currentMaterial.setIlluminationModel(value);
		}
		
		
	}
	
	private void d(String line){
		line = removeComments(line);
		
		String[] arr = line.split(" ");
		
		float value = 0;
		
		int h = 0;
		for(int i=0;i<arr.length;i++){
			if(!arr[i].equals("")){
				h++;
				switch(h){
				case 1:
					value = Float.parseFloat(arr[i]);
					break;
				default:
					break;
				}
			}
		}
		
		if(currentMaterial != null){
			currentMaterial.setDissolve(value);
		}
		
		
	}
	
	
	public Geometry_Material getMaterial(String materialName){
		return materials.get(materialName);
	}
	
}
